package com.ai.controller.networking;


import com.ai.annotation.EnterPathParamLog;
import com.ai.common.CommonResponse;
import com.ai.common.constant.PlcConstants;
import com.ai.entity.cameraFunctions.FullFunction;
import com.ai.entity.comm.SysNetty;
import com.ai.entity.network.IdentifySysToL1Message;
import com.ai.networking.netty.client.BootNettyClientChannel;
import com.ai.networking.netty.client.BootNettyClientChannelCache;
import com.ai.networking.netty.client.BootNettyClientThread;
import com.ai.networking.netty.comm.CommonNetty;
import com.ai.util.StringUtil;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author chen
 * @since 2023-04-03 21:17:12
 */
@RestController
@RequestMapping("/sys-netty")
@Slf4j
public class SysNettyController {

    @GetMapping("messageTest/{code}/{num}")
    @ApiOperation("获取全部功能，以及功能对应的摄像头详细")
    @EnterPathParamLog
    public CommonResponse messageTest(@PathVariable(name = "code") String plcCode,
                                      @PathVariable(name = "num") String num) {
        sendHeart(plcCode,num);
        return CommonResponse.ok("心跳报文已发送");
    }

    @GetMapping("alarmMessageTest/{code}")
    @ApiOperation("获取全部功能，以及功能对应的摄像头详细")
    @EnterPathParamLog
    public CommonResponse alarmMessageTest(@PathVariable(name = "code") String plcCode) {

        IdentifySysToL1Message identifySysToL1Message = new IdentifySysToL1Message();
        identifySysToL1Message.setTelID(PlcConstants.RETURN_TO_MESSAGE_A3_TRANSFER_MACHINE)
                .setPlanNo("C123456789")
                .setDoorNum("1")
                .setResult(1);



        BootNettyClientChannel bootNettyChannel = BootNettyClientChannelCache.channelMapCache.get(plcCode);
        if (bootNettyChannel != null && bootNettyChannel.getChannel().isOpen() ) {
            byte[] messageBytes;
            if("plc_1".equals(plcCode)){
                 messageBytes = createMessageToPlc1(identifySysToL1Message);
            }else{
                messageBytes = createMessageToPlcOther(identifySysToL1Message);
            }

            log.info("=========================== 向发送 {} 警報報文  ===========================",plcCode);
            log.info("=========================== 報文内容:{}  ===========================",messageBytes);
            bootNettyChannel.getChannel().writeAndFlush(Unpooled.copiedBuffer(messageBytes));
//                        bootNettyChannel.getChannel().writeAndFlush(Unpooled.copiedBuffer(heartJson, CharsetUtil.UTF_8));
//                        bootNettyChannel.getChannel().writeAndFlush(Unpooled.buffer().writeBytes(back.getBytes()));
        }

        return CommonResponse.ok("报文已发送");
    }

    public static void  sendHeart(String plcCode,String num) {
        // 心跳自定义


        // 所有已经连接的客户端
        if (CommonNetty.NATIVE_CLIENT_MAP.size() > 0) {
            //所有需要并且已经连接的客户端
            for (Map.Entry<String, SysNetty> entry : CommonNetty.NATIVE_CLIENT_MAP.entrySet()) {
                String code = entry.getKey();
                SysNetty sysNetty = entry.getValue();

                if (!code.equals(plcCode)){
                    continue;
                }
                // 判断是否创建成功   ----------   通过code来判断对应的功能是哪个
                if (BootNettyClientChannelCache.channelMapCache.containsKey(code)) {
                    // 创建成功
                    BootNettyClientChannel bootNettyChannel = BootNettyClientChannelCache.channelMapCache.get(code);
                    if (bootNettyChannel != null && bootNettyChannel.getChannel().isOpen() ) {
                        // : 2023-06-20 修改心跳信号内容----不同的端口 发送的心跳内容不同
                        byte[] heartJson = createHeartJson(code,num);
                        log.info("=========================== 向发送 {} 心跳  ===========================",code);
                        log.info("=========================== 心跳内容:{}  ===========================",heartJson);
                        bootNettyChannel.getChannel().writeAndFlush(Unpooled.copiedBuffer(heartJson));
//                        bootNettyChannel.getChannel().writeAndFlush(Unpooled.copiedBuffer(heartJson, CharsetUtil.UTF_8));
//                        bootNettyChannel.getChannel().writeAndFlush(Unpooled.buffer().writeBytes(back.getBytes()));
                    }
                } else {
                    log.info(code + "创建失败,准备重连...");
                    new BootNettyClientThread(sysNetty).start();
                }
            }
        }
    }

    /**
     * 創建給其他plc1的回調信息
     * @param identifySysToL1Message
     * @return
     */
    private static byte[] createMessageToPlc1(IdentifySysToL1Message identifySysToL1Message){
        short messageLength=46;
        byte[] messageBytes = new byte[46];
        // 消息長度 2
        StringUtil.byteInsert(messageBytes, StringUtil.intToByteArray(messageLength,2),0);
        // 信號telId 6位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(identifySysToL1Message.getTelID().toString()),2);
        // 板坯號 12位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(identifySysToL1Message.getPlanNo()),8);
        //識別結果 2位
        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(identifySysToL1Message.getResult(),2),20);
        //預留字段 24位
        String spare= (StringUtils.isBlank(identifySysToL1Message.getSpare())?"":identifySysToL1Message.getSpare());
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(spare),22);

        String messageToPlc1 = Arrays.toString(messageBytes);
        return messageBytes;
    }

    /**
     * 創建給其他plc的回調信息
     * @param identifySysToL1Message
     * @return
     */
    private static byte[]  createMessageToPlcOther(IdentifySysToL1Message identifySysToL1Message) {
        short messageLength=46;
        byte[] messageBytes = new byte[46];
        // 消息長度 2
        StringUtil.byteInsert(messageBytes, StringUtil.intToByteArray(messageLength,2),0);
        // 信號telId 6位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(identifySysToL1Message.getTelID().toString()),2);
        // 板坯號 12位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(identifySysToL1Message.getPlanNo()),8);
        //爐門編號 2位
        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(Integer.valueOf(identifySysToL1Message.getDoorNum(),2)),20);
        //識別結果 2位
        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(identifySysToL1Message.getResult(),2),22);
        //預留字段 22位
        String spare= (StringUtils.isBlank(identifySysToL1Message.getSpare())?"":identifySysToL1Message.getSpare());
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(spare),24);

        String messageToPlc = Arrays.toString(messageBytes);
        return messageBytes;
    }



    /**
     * 不同的nettyCode返回不同的心跳电文
     * @param plcCode
     * @return
     */
    public static byte[] createHeartJson(String plcCode,String num){
        String telId="";
        if (plcCode.equals(PlcConstants.PLC_1_CODE)){
            telId=PlcConstants.PLC_1_HEART_TEL_ID;
        }else if (plcCode.equals(PlcConstants.PLC_2_CODE)){
            telId=PlcConstants.PLC_2_HEART_TEL_ID;
        }else {
            //plc_3
            telId=PlcConstants.PLC_3_HEART_TEL_ID;
        }

        short heartLength=46;
        byte[] heartBytes = new byte[46];

        //心跳電文長度 2位
        StringUtil.byteInsert(heartBytes, StringUtil.intToByteArray(heartLength,2),0);

        //telId 6位
        StringUtil.byteInsert(heartBytes, StringUtil.convertStringToHex(telId),2);

        //counter 2位
        StringUtil.byteInsert(heartBytes, StringUtil.convertStringToHex(num),8);

        //Spare 36位
        StringUtil.byteInsert(heartBytes, StringUtil.convertStringToHex(""),10);

        String s = new String(heartBytes);
        String heartMessage = Arrays.toString(heartBytes);
        return heartBytes;
    }



}

